package com.gskj.aclservice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gskj.aclservice.entity.Permission;
import com.gskj.aclservice.entity.RolePermission;
import com.gskj.aclservice.helper.MemuHelper;
import com.gskj.aclservice.helper.PermissionHelper;
import com.gskj.aclservice.mapper.PermissionMapper;
import com.gskj.aclservice.service.PermissionService;
import com.gskj.aclservice.service.RolePermissionService;
import com.gskj.aclservice.service.UserService;
import com.gskj.aclservice.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 权限 服务实现类
 * </p>
 *
 * @author testjava
 * @since 2020-01-12
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    @Autowired
    private RolePermissionService rolePermissionService;

    @Autowired
    private UserService userService;


    //获取全部菜单
    @Override
    public List<Permission> queryAllMenu() {

        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<Permission> permissionList = baseMapper.selectList(wrapper);

        List<Permission> result = bulid(permissionList);

        return result;
    }

    //根据角色获取菜单
    @Override
    public List<Permission> selectAllMenu(String roleId) {
        List<Permission> allPermissionList = baseMapper.selectList(new QueryWrapper<Permission>().orderByAsc("CAST(id AS SIGNED)"));

        //根据角色id获取角色权限
        List<RolePermission> rolePermissionList = rolePermissionService.list(new QueryWrapper<RolePermission>().eq("role_id", roleId));
        //转换给角色id与角色权限对应Map对象
//        List<String> permissionIdList = rolePermissionList.stream().map(e -> e.getPermissionId()).collect(Collectors.toList());
//        allPermissionList.forEach(permission -> {
//            if(permissionIdList.contains(permission.getId())) {
//                permission.setSelect(true);
//            } else {
//                permission.setSelect(false);
//            }
//        });
        for (int i = 0; i < allPermissionList.size(); i++) {
            Permission permission = allPermissionList.get(i);
            for (int m = 0; m < rolePermissionList.size(); m++) {
                RolePermission rolePermission = rolePermissionList.get(m);
                if (rolePermission.getPermissionId().equals(permission.getId())) {
                    permission.setSelect(true);
                }
            }
        }


        List<Permission> permissionList = bulid(allPermissionList);
        return permissionList;
    }

    //给角色分配权限
    @Override
    public void saveRolePermissionRealtionShip(String roleId, String[] permissionIds) {

        rolePermissionService.remove(new QueryWrapper<RolePermission>().eq("role_id", roleId));


        List<RolePermission> rolePermissionList = new ArrayList<>();
        for (String permissionId : permissionIds) {
            if (StringUtils.isEmpty(permissionId)) continue;

            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(roleId);
            rolePermission.setPermissionId(permissionId);
            rolePermissionList.add(rolePermission);
        }
        rolePermissionService.saveBatch(rolePermissionList);
    }

    //递归删除菜单
    @Override
    public void removeChildById(String id) {
        List<String> idList = new ArrayList<>();
        this.selectChildListById(id, idList);

        idList.add(id);
        baseMapper.deleteBatchIds(idList);
    }

    //根据用户id获取用户菜单
    @Override
    public List<String> selectPermissionValueByUserId(String id) {

        List<String> selectPermissionValueList = null;
        if (this.isSysAdmin(id)) {
            //如果是系统管理员，获取所有权限
            selectPermissionValueList = baseMapper.selectAllPermissionValue();
        } else {
            selectPermissionValueList = baseMapper.selectPermissionValueByUserId(id);
        }
        return selectPermissionValueList;
    }

    @Override
    public List<JSONObject> selectPermissionByUserId(String userId) {
        List<Permission> selectPermissionList = null;
        if (this.isSysAdmin(userId)) {
            //如果是超级管理员，获取所有菜单
            selectPermissionList = baseMapper.selectList(null);
        } else {
            selectPermissionList = baseMapper.selectPermissionByUserId(userId);
        }

        List<Permission> permissionList = PermissionHelper.bulid(selectPermissionList);
        List<JSONObject> result = MemuHelper.bulid(permissionList);
        return result;
    }

    /**
     * 判断用户是否系统管理员
     *
     * @param userId
     * @return
     */
    private boolean isSysAdmin(String userId) {
        User user = userService.getById(userId);

        if (null != user && "admin".equals(user.getUsername())) {
            return true;
        }
        return false;
    }

    /**
     * 递归获取子节点
     */
    private void selectChildListById(String id, List<String> idList) {
        List<Permission> childList = baseMapper.selectList(new QueryWrapper<Permission>().eq("pid", id).select("id"));
        childList.stream().forEach(item -> {
            idList.add(item.getId());
            this.selectChildListById(item.getId(), idList);
        });
    }

    /**
     * 使用递归方法建菜单
     */
    private static List<Permission> bulid(List<Permission> treeNodes) {
        List<Permission> trees = new ArrayList<>();
        for (Permission treeNode : treeNodes) {
            if ("0".equals(treeNode.getPid())) {
                treeNode.setLevel(1);
                trees.add(findChildren(treeNode, treeNodes));
            }
        }
        return trees;
    }

    /**
     * 递归查找子节点
     *
     * @param treeNodes
     * @return
     */
    private static Permission findChildren(Permission treeNode, List<Permission> treeNodes) {
        treeNode.setChildren(new ArrayList<Permission>());

        for (Permission it : treeNodes) {
            if (treeNode.getId().equals(it.getPid())) {
                int level = treeNode.getLevel() + 1;
                it.setLevel(level);
                if (treeNode.getChildren() == null) {
                    treeNode.setChildren(new ArrayList<>());
                }
                treeNode.getChildren().add(findChildren(it, treeNodes));
            }
        }
        return treeNode;
    }


    //========================递归查询所有菜单================================================

    //获取全部菜单
    @Override
    public List<Permission> queryAllMenuGuli() {
        //1 查询菜单表所有数据
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<Permission> permissionList = baseMapper.selectList(wrapper);
        //2 把查询所有菜单list集合按照要求进行封装
        List<Permission> resultList = bulidPermission(permissionList);
        return resultList;
    }

    /**
     * 把返回所有菜单list集合进行封装的方法,返回层次list
     */
    public static List<Permission> bulidPermission(List<Permission> permissionList) {
        // 创建集合，用于最终封装的信息
        List<Permission> findNode = new ArrayList<>();
        // 1. 遍历集合，得到顶层菜单 pid =0， 设置level = 1；  为一级菜单
        permissionList.forEach(permissionNode -> {
            if ("0".equals(permissionNode.getPid())) {
                // 设置 level =1；
                permissionNode.setLevel(1);

                // 根据顶层菜单，向里面查询子菜单，封装到findNode中
                findNode.add(selectChildren(permissionNode, permissionList));
            }
        });
        return findNode;
    }


//     根据传入的 一层菜单，所有菜单，
//     封装 一层下面的 二、三 ...层菜单

    private static Permission selectChildren(Permission permissionNode, List<Permission> permissionList) {
        // 遍历 查询 二、三、四 层菜单那
        permissionList.forEach(permission -> {
            // 判断 一层菜单id 是否等于  二层菜单.pid
            if (permissionNode.getId().equals(permission.getPid())) {
                // 将父菜单 level +1， 即为 二级菜单level :2
                int level = permissionNode.getLevel();
                permission.setLevel(level);
                if (permission.getChildren() == null) {
                    // 初始化 二层菜单....
                    permissionNode.setChildren(new ArrayList<Permission>());
                }
                // 将查询的子菜单 放入 父菜单
                // 利用递归 再次查询并封装 子菜单到 父菜单
                permissionNode.getChildren().add(selectChildren(permission, permissionList));
            }
        });
        return permissionNode;
    }


    @Override
    public List<Permission> queryAllMenuThird() {
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        // 所有菜单
        List<Permission> permissions = this.baseMapper.selectList(wrapper);
        // 最重要返回的数据
        List<Permission> node = new ArrayList<>();

        // 遍历查询的所有菜单集合，找出一级菜单
        for (Permission permissionNode : permissions) {
            // 得到顶层菜单  pid= 0
            if ("0".equals(permissionNode.getPid())) {
                //设置 level值为1 ： 一级菜单
                permissionNode.setLevel(1);

                //TODO 使用递归查询
                // 根据顶层菜单，继续向里面查询子菜单，保存到 node集合中
                Permission permission = selectChildrenThird(permissionNode, permissions);
                node.add(permission);
            }
        }
        return node;
    }

    /**
     * 递归删除菜单
     *
     * @param id
     */
    @Override
    public void removeChildByIdThird(String id) {
        // 保存要删除的菜单的id值
        List<String> ids = new ArrayList<>();

        // 想list中存放指定id 下所有的子菜单id
        this.selectPermissionChildrenById(id, ids);
        // 最好将 id也保存到 ids中。
        // 递归只是把id对应的所有子菜单id保存，没有保存当前菜单id
        ids.add(id);

        //  删除菜单
        this.baseMapper.deleteBatchIds(ids);
    }

    /***
     *  给角色分配权限
     */
    @Override
    public void saveRolePermissionRealtionShipThird(String roleId, String[] permissionId) {
        // role id
        // permission id

        // 创建集合保存 角色id，权限id
        List<RolePermission> list = new ArrayList<>();
        for (String pid
                : permissionId) {
            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(roleId);
            rolePermission.setId(pid);

            list.add(rolePermission);
        }
        // 批量添加
        rolePermissionService.saveBatch(list);
    }

    /**
     * 通过指定id，返回该id下所有子菜单id
     */
    private void selectPermissionChildrenById(String id, List<String> ids) {
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        // 添加查询条件
        wrapper.eq("pid", id);
        // 指定查询字段
        wrapper.select("id");
        List<Permission> permissions = this.baseMapper.selectList(wrapper);

        permissions.stream().forEach(item -> {
            String itemId = item.getId();
            ids.add(itemId);
            // TODO 再次调用递归。
            this.selectPermissionChildrenById(itemId, ids);
        });
    }


    /**
     * 递归查询 树形结构菜单。
     *
     * @param permissionNode 一级菜单
     * @param permissions    所有菜单
     */
    private Permission selectChildrenThird(Permission permissionNode, List<Permission> permissions) {
        // 初始化一级菜单，children值。 后续二级、三级都会添加到一级中的children集合中去
        permissionNode.setChildren(new ArrayList<>());

        // 遍历所有菜单集合， 进行判断比较。对比id、pid是否一致
        for (Permission it : permissions) {
            // 判断 id、pid是否一致
            if (permissionNode.getId().equals(it.getPid())) {
                // 父菜单 level++
                int level = permissionNode.getLevel() + 1;
                it.setLevel(level);

                if (it.getChildren() == null) {
                    it.setChildren(new ArrayList<>());
                }
                // 继续调用递归查询下下级的查询。
                permissionNode.getChildren().add(selectChildrenThird(it, permissions));
            }
        }
        return permissionNode;
    }
}
